#include "KernelPolynomialMethod.h"

const string KMP::biassymbol = "Bias";
const string KMP::wavevectorsymbol = "WaveVector";
const string KMP::boundtolsymbol = "Eta";
const string KMP::nrandsymbol = "RandomStates";
const string KMP::npolysymbol = "ChebyshevStates";

void KMP::getDoS(int id)
{
	// The functor constructed and options are pulled from expression!
	KernelPolynomialMethod kpm = getWithParameters();

	if(kpm.x.size() == 1)
		return;

	mat result(2,kpm.x.n_rows);
	result.row(0) = arma::real(kpm.x).t();
	result.row(1) = kpm.calcDoS(id).DoS.t();

	MLPutValue(stdlink,result);
}

KernelPolynomialMethod KMP::getWithParameters()
{
	// The resulting functor is allocated!
	KernelPolynomialMethod kpm;

	// The energy range is supplied first!
	numeric::range energy_range;
	if(!MLGetValue(stdlink,&energy_range))
		return kpm;
	kpm.x = arma::ones<cx_vec>(energy_range.size())*energy_range.step;
	kpm.x(0) = (complex)energy_range.begin;
	kpm.x = arma::cumsum(kpm.x);
	
	// The options are then supplied.
	rule::list opts;
	if(!MLGetValue(stdlink,&opts))
		return kpm;

	// Now we set the options!
	const size_t rulesize = opts.size();
	for(size_t r = 0; r < rulesize; r++)
	{
		// Rules from Mathematica always have symbols first.
		if(!opts[r].first.isSymbolType())
			continue;
		
		// The variable is pulled out.
		symbol sym = opts[r].first.toSymbol();
		variant var = opts[r].second;
		
		if(sym.name() == biassymbol)
		{
			if(var.isNumericType())
				kpm.bias = var.toDouble();
		}
		else if(sym.name() == wavevectorsymbol)
		{
			if(var.isNumericListType())
				kpm.k = var.toArmaDoubleVector3();
		}
		else if(sym.name() == boundtolsymbol)
		{
			if(var.isNumericType())
				kpm.tol_bounds = var.toDouble();
			else if(var.isSymbolType() && var.toSymbol().reference() == symbol::none)
				kpm.tol_bounds = 0;
		}
		else if(sym.name() == nrandsymbol)
		{
			if(var.isNumericType())
				kpm.N_rand = var.toSize();
		}
		else if(sym.name() == npolysymbol)
		{
			if(var.isNumericType())
				kpm.N_poly = var.toSize();
		}
	}

	return kpm;
}